package com.coding.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;
import lombok.extern.java.Log;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

@Log
public class JWTUtils {
    public static String privateKeyStr = "";
    public static String publicKeyStr = "";

    static {
        try {
            getKey();
        } catch (NoSuchAlgorithmException e) {
            log.warning("获取密钥失败"+e.getMessage());
        }
    }


    public static String getToken(Claims claims) {
        // 将私钥和公钥进行Base64解码
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
        try {
            // 构建私钥和公钥对象
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            //PKCS8EncodedKeySpec和X509EncodedKeySpec分别创建私钥和公钥的规格对象
            PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
            PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
            // 构建JWT token
            String token = Jwts.builder()
                    .issuer("LinWeiJun")
                    .claims(claims)// 设置token的负载
                    .subject("user") // 设置token的主题，通常是代表用户的标识符。
                    .issuedAt(new Date()) // 设置token的签发时间
//                    .expiration(new Date(System.currentTimeMillis() + expireTime)) // 设置token的过期时间1h
                    .signWith(privateKey) // 使用私钥进行签名
                    .compact();

            System.out.println("JWT token: " + token);
            return token;
        } catch (Exception e) {
            log.warning("生成token失败");
        }

        return null;
    }


    /**
     * 生成一个RSA算法的密钥对（公钥和私钥），并将其以Base64编码的字符串形式保存
     *
     * @throws NoSuchAlgorithmException
     */
    private static void getKey() throws NoSuchAlgorithmException {

        //获取一个RSA算法的密钥对生成器。
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048); // 设置密钥长度为2048位。
        KeyPair keyPair = keyPairGenerator.generateKeyPair();//生成密钥对，并将其保存在keyPair对象中。

        // 获取公钥的字节数组，将其编码为字符串形式
        publicKeyStr = Encoders.BASE64.encode(keyPair.getPublic().getEncoded());
        privateKeyStr = Encoders.BASE64.encode(keyPair.getPrivate().getEncoded());

        System.out.println("Public Key: " + publicKeyStr);
        System.out.println("Private Key: " + privateKeyStr);
    }

    public static Claims verify(String publicKeyStr, String token)  {
        // 将公钥进行Base64解码
        byte[] publicKeyBytes = Decoders.BASE64.decode(publicKeyStr);
        try {
            // 构建公钥对象
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBytes));

            //创建一个JWT解析器，使用公钥来验证JWT的签名，构建JWT解析器实例，解析指定的签名JWT令牌，获取JWT令牌的有效载荷部分
            Claims claims = Jwts.parser().verifyWith(publicKey).build().parseSignedClaims(token).getPayload();
            log.info("Issuer: " + claims.getIssuer());

            return claims;
        }  catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            log.warning("密钥格式错误："+e.getMessage());
            return null;
        }

    }

}
